home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / scope / 051-075 / scopedisk69 / bval / beval.c < prev    next >
C/C++ Source or Header  |  1995-03-19  |  7KB  |  375 lines

  1. /* Designed, written and commented by Paul Falstad */
  2. /* This program was extracted from a much, much larger program */
  3. /* by the same author, so don't expect streamlined code.       */
  4.  
  5. extern double Term1(),Parens(),LocalConv(),Term2();
  6. char *Eval(),*FetchSym(),*SkipSpace(),*RetPDB();
  7.  
  8. main(argc,argv)
  9. int argc;
  10. char **argv;
  11. {
  12.    if (argc != 2)
  13.       printf("Format: %s (expression)\n",argv[0]);
  14.    else
  15.       {
  16.       printf(Eval(argv[1],0,0L));
  17.       printf("\n");
  18.       }
  19. }
  20.  
  21. int isstring(str)
  22. char *str;
  23. {
  24. int isstring = TRUE,parens = 0;
  25.  
  26.    while (*str)
  27.       {
  28.       if (*str == '(')
  29.          parens++;
  30.       if (*str == ')')
  31.          parens--;
  32.       if (parens)
  33.          {
  34.          str++;
  35.          continue;
  36.          }
  37.       if (*str == '+' || *str == '-' || *str == '*' || *str == '/' ||
  38.           *str == '^' || *str == '%' || (*str >= '0' && *str <= '9'))
  39.          {
  40.          isstring = FALSE;
  41.          break;
  42.          }
  43.       str++;
  44.       }
  45.    return(isstring);
  46. }
  47.  
  48. char *Eval(str,rnd,db)
  49. char *str;
  50. int rnd;
  51. double *db;
  52. {
  53. double val = 0;
  54. static char ebuf[512];
  55.  
  56.    while (*str == ' ')
  57.       str++;
  58.    if (!*str)
  59.       return(0);
  60.    if (isstring(str))
  61.       return(FetchSym(str,0L));
  62.    while (*str)
  63.       val += Term1(&str);
  64.    if (db)
  65.       {
  66.       *db = val;
  67.       return(0L);
  68.       }
  69.    else
  70.       {
  71.       DoublePrint(ebuf,val,8);
  72.       return(SkipSpace(ebuf));
  73.       }
  74. }
  75.  
  76. double Term1(str)
  77. char **str;
  78. {
  79. char *ptr,buf[80];
  80. long paren = 0;
  81. BOOL first;
  82.  
  83.    if (**str == 0)
  84.       return(0);
  85.    sprintf(buf,"+%s",*str);
  86.    first = TRUE;
  87.    for (ptr = buf+1; *ptr; ptr++,(*str)++)
  88.       {
  89.       if (*ptr == '(')
  90.          paren++;
  91.       if (*ptr == ')')
  92.          paren--;
  93.       if (paren)
  94.          continue;
  95.       if (*ptr == '-' && first)
  96.          {
  97.          first = FALSE;
  98.          continue;
  99.          }
  100.       first = FALSE;
  101.       if (*ptr == '*' || *ptr == '/' || *ptr == '^' || *ptr == '%'
  102.                       || *ptr == '^')
  103.          {
  104.          first = TRUE;
  105.          continue;
  106.          }
  107.       if (*ptr == '+' || *ptr == '-')
  108.          break;
  109.       }
  110.    if (paren)
  111.       return(0);
  112.    *ptr = NULL;
  113.    if (**str == '+')
  114.       (*str)++;
  115.    return(Term2(buf));
  116. }
  117.  
  118. double Parens(str)
  119. char *str;
  120. {
  121. char buf[70],*pt;
  122. long parct = 1;
  123. double ret = 0;
  124.  
  125.    sprintf(buf,"%s",str+1);
  126.    for (pt = buf; *pt; pt++)
  127.       {
  128.       if (*pt == '(')
  129.          parct++;
  130.       if (*pt == ')')
  131.          parct--;
  132.       if (!parct)
  133.          break;
  134.       }
  135.    if (parct)
  136.       return(0);
  137.    *pt = NULL;
  138.    pt = buf;
  139.    while (*pt)
  140.       ret += Term1(&pt,&ret);
  141.    return(ret);
  142. }
  143.  
  144. double LocalConv(ch)
  145. char *ch;
  146. {
  147. double val = 0.0,shift = .100;
  148. long mult = 1;
  149. BOOL ped = FALSE;
  150.  
  151.    while (*ch)
  152.       {
  153.       if (*ch == '.')
  154.          {
  155.          ped = TRUE;
  156.          ch++;
  157.          continue;
  158.          }
  159.       if (*ch == '-' && val == 0 && mult == 1)
  160.          {
  161.          mult = -1;
  162.          ch++;
  163.          continue;
  164.          }
  165.       if (*ch == '*' || *ch == '/' || *ch == '%' || *ch == '^' || *ch == ' ')
  166.          break;
  167.       if (*ch < '0' || *ch > '9')
  168.          return(0);
  169.       if (ped)
  170.          {
  171.          val += shift*(*ch-'0');
  172.          shift /= 10;
  173.          }
  174.       else
  175.          val = val*10+(*ch-'0');
  176.       ch++;
  177.       }
  178.    return(val*mult);
  179. }
  180.  
  181. double Term2(str)
  182. char *str;
  183. {
  184. double a = 0,b;
  185. long paren = 0;
  186.  
  187.    while (*str)
  188.       {
  189.       if (*(str+1) == '(')
  190.          b = Parens(str+1);
  191.       else
  192.          {
  193.          if (tolower(*(str+1)) >= 'a' && tolower(*(str+1)) <= 'z')
  194.             FetchSym(str+1,&b);
  195.          else
  196.             {
  197.             if (*(str+1) == '-')
  198.                {
  199.                if (tolower(*(str+2)) >= 'a' && tolower(*(str+2)) <= 'z')
  200.                   {
  201.                   FetchSym(str+2,&b);
  202.                   b = -b;
  203.                   }
  204.                else
  205.                  {
  206.                  if (*(str+2) == '(')
  207.                     b = -Parens(str+2);
  208.                  else
  209.                     b = LocalConv(str+1);
  210.                  }
  211.                }
  212.             else
  213.                b = LocalConv(str+1);
  214.             }
  215.          }
  216.       switch (*str)
  217.          {
  218.          case '+':
  219.             a = b;
  220.             break;
  221.          case '*':
  222.             a *= b;
  223.             break;
  224.          case '/':
  225.             if (b != 0)
  226.                a /= b;
  227.             else
  228.                a = 0;
  229.             break;
  230.          case '%':
  231.             if (b != 0)
  232.                a = (int) a % (int) b;
  233.             else
  234.                a = 0;
  235.             break;
  236.          case '^':
  237.             a = pow(a,b);
  238.             break;
  239.          default:
  240.             return(0);
  241.          };
  242.       for (str++; *str; str++)
  243.          {
  244.          if (*str == '(')
  245.             paren++;
  246.          if (*str == ')')
  247.             {
  248.             paren--;
  249.             continue;
  250.             }
  251.          if (paren)
  252.             continue;
  253.          if (*str == '*' || *str == '/' || *str == '%' || *str == '^')
  254.             break;
  255.          }
  256.       }
  257.    return(a);
  258. }
  259.  
  260. char *FetchSym(str,pdb)
  261. char *str;
  262. double *pdb;
  263. {
  264. char *pt,*tp;
  265. static char stufbuf[80],dobuf[80];
  266. int s0;
  267. double arg;
  268.  
  269.    for (pt = str; *pt; pt++)
  270.       if ((tolower(*pt) < 'a' || tolower(*pt) > 'z') &&
  271.          (*pt < '0' || *pt > '9') && *pt != '_')
  272.          break;
  273.    for (tp = stufbuf; str != pt; str++,tp++)
  274.       *tp = tolower(*str);
  275.    *tp = 0;
  276.    if (*pt == '(')
  277.       {
  278.       if (!strcmp("int",stufbuf))
  279.          return(RetPDB((double) ((long) Parens(pt)),pdb));
  280.       if (!strcmp("abs",stufbuf))
  281.          return(RetPDB(abs(Parens(pt)),pdb));
  282.       if (!strcmp("sqrt",stufbuf))
  283.          return(RetPDB(sqrt(Parens(pt)),pdb));
  284.       if (!strcmp("sin",stufbuf))
  285.          return(RetPDB(sin(Parens(pt)/180*PI),pdb));
  286.       if (!strcmp("cos",stufbuf))
  287.          return(RetPDB(cos(Parens(pt)/180*PI),pdb));
  288.       if (!strcmp("tan",stufbuf))
  289.          return(RetPDB(tan(Parens(pt)/180*PI),pdb));
  290.       if (!strcmp("ln",stufbuf))
  291.          {
  292.          arg = Parens(pt);
  293.          if (arg <= 0)
  294.             return(RetPDB((double) 0,pdb));
  295.          else
  296.             return(RetPDB(log(arg),pdb));
  297.          }
  298.       if (!strcmp("log",stufbuf))
  299.          {
  300.          arg = Parens(pt);
  301.          if (arg <= 0)
  302.             return(RetPDB((double) 0,pdb));
  303.          else
  304.             return(RetPDB(log10(arg),pdb));
  305.          return;
  306.          }
  307.       if (!strcmp("atan",stufbuf))
  308.          return(RetPDB(atan(Parens(pt))/PI*180,pdb));
  309.       }
  310.    if (!strcmp(stufbuf,"pi"))
  311.       {
  312.       if (pdb)
  313.          {
  314.          *pdb = PI;
  315.          return;
  316.          }
  317.       else
  318.          return("3.141592654");
  319.       }
  320.    if (!strcmp(stufbuf,"e"))
  321.       {
  322.       if (pdb)
  323.          {
  324.          *pdb = 2.718281828;
  325.          return;
  326.          }
  327.       else
  328.          return("2.718281828");
  329.       }
  330. }
  331.  
  332. char *RetPDB(db,dbp)
  333. double db,*dbp;
  334. {
  335. static char pdbuf[512];
  336.  
  337.    if (dbp)
  338.       {
  339.       *dbp = db;
  340.       return(NULL);
  341.       }
  342.    else
  343.       {
  344.       DoublePrint(pdbuf,db,8);
  345.       return(SkipSpace(pdbuf));
  346.       }
  347. }
  348.  
  349. DoublePrint(buf,val,sigs)
  350. char *buf;
  351. double val;
  352. int sigs;
  353. {
  354. int ptr;
  355.  
  356.    sprintf(buf,"%60.*f",sigs,val);
  357.    for (ptr = 59; ptr; ptr--)
  358.       {
  359.       if (buf[ptr] == '0')
  360.          buf[ptr] = 0;
  361.       else
  362.          break;
  363.       }
  364.    if (buf[ptr] == '.')
  365.       buf[ptr] = 0;
  366. }
  367.  
  368. char *SkipSpace(ptr)
  369. char *ptr;
  370. {
  371.    while (*ptr == ' ')
  372.       ptr++;
  373.    return(ptr);
  374. }
  375.